/**
 * 快速实现双向数据绑定
 * 1.数据 -> 响应式数据 Object.defineProperty Proxy
 * 2.input -> input/keyup -> 事件处理函数的绑定 ->绑定数据
 * 3.相关的Dom-> 数据 => 绑定在一起
 *     操作数据的某个属性-> 对应的Dom改变
 * 2.完成数据响应式设置
 * 3.input 事件处理函数的绑定
 * 4.实现数据与DOM节点绑定
 * 5.用Proxy实现、实现变更数据更新视图
 */

class Mvvm {
    constructor(el, data) {
        this.el = document.querySelector(el);
        // this._data = data;
        this.data = data;
        this.domPool = {};

        this.init()
    }

    init() {
        this.initData();
        this.initDom();
    }
    initDom() {
        this.bindDom(this.el);
        this.bindInput(this.el);
    }
    //数据响应式设置
    initData() {
        let _this = this;
        // this.data = {};
        // for (let key in this._data) {
        //     Object.defineProperty(this.data, key, {
        //         get() {
        //             return _this._data[key]
        //         },
        //         set( newValue ) {
        //             _this.domPool[key].innerHTML = newValue;
        //             _this._data[key] = newValue;
        //         }
        //     })
        // }

        this.data = new Proxy(this.data, {
            set (target, key) {
                return Reflect.get(target, key);
            },
            set (target, key, value) {
                _this.domPool[key].innerHTML = value;
                return Reflect.set(target, key, value)
            }
        })

    }
    //实现数据与DOM节点绑定
    bindDom(el) {
        const childNodes = el.childNodes;
        childNodes.forEach(item => {
            if (item.nodeType === 3) {
                const _value = item.nodeValue;
                if (_value.trim().length) {
                    let _isValid = /\{\{(.+?)\}\}/.test(_value);
                    if (_isValid) {
                         const _key = _value.match(/\{\{(.+?)\}\}/)[1].trim();
                         this.domPool[_key] = item.parentNode;
                        item.parentNode.innerText = this.data[_key] || undefined;
                    }
                }
            }
            item.childNodes && this.bindDom(item);
        })
    }
    //input事件处理函数的绑定
    bindInput(el) {
        const _allInputs = el.querySelectorAll('input');
        _allInputs.forEach(input => {
            const _vModel = input.getAttribute('v-model');
            if (_vModel) {
                input.addEventListener('keyup', this.handleInput.bind(this, _vModel, input), false)
            }
        })
    }

    handleInput(key, input) {
        const _value = input.value;
        this.data[key] = _value;
    }

    setData (key, value){
        this.data[key] = value
    }
}